﻿using SuporeSliplampApp.Models;
using SuporeSliplampApp.Util;
using SuporeSliplampApp.ViewModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Windows.Interop;
using static SuporeSliplampApp.Models.CameraModel;
using static SuporeSliplampApp.Util.util;
using SuporeSliplampApp.Control;
using static SuporeSliplampApp.Models.MainModel;

namespace SuporeSliplampApp.Views
{
    /// <summary>
    /// CamaraView.xaml 的交互逻辑
    /// </summary>
    public partial class CamaraView : UserControl
    {
        public static uvcham cam_ = null;
        private WriteableBitmap bmp_ = null;
        public static IntPtr buf_ = IntPtr.Zero;
        private DispatcherTimer timer_ = null;
        private static bool started_ = false;
        private static bool successed = false;
        private uint count_ = 0;
        private delegate void msg(string s);
        BackgroundWorker worker;
        //窗体最大化
        private Window _fullScreenWindow = null;
        private DependencyObject _originalParent = null;
        private Grid grid = null;
        bool _maxed = false;
        int index = -1;
        private CameraSettingWindow  settingWindow = null;
        public static event EventHandler<string> openImageDelegate;

        //public static List<Dictionary<string, Dictionary<string, int>>> rangeList = new List<Dictionary<string, Dictionary<string, int>>>();
        //private Dictionary<string, Dictionary<string, int>> rangeDic = new Dictionary<string, Dictionary<string, int>>();

        [DllImport("User32.dll",EntryPoint ="FindWindow")]
        private static extern IntPtr FindWindow(string classname, string name);

        [DllImport("User32.dll", EntryPoint = "SetParent")]
        private static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
        public  CamaraView()
        {
            InitializeComponent();
            _originalParent = this.Parent;
            this.Unloaded += (s, e) => { stopCamera(); };
            var fa = VisualTreeHelper.GetParent(this.testgrid);
            grid = (Grid)fa;
            loadCamera();
            this.DataContext = new CameraViewModel();
           // ScrollControl.scrollDelegate += ScrollControl_scrollDelegate;
           // EditPicControl.analyseDalegate += EditPicControl_analyseDalegate;


        }

        private void EditPicControl_analyseDalegate(object sender, ListControlModel e)
        {
            ListControlModel model = new ListControlModel { ImgPath = e.ImgPath, Name = e.Name };
            ScrollControl scrollControl = new ScrollControl();
            TextBlock textBlock = new TextBlock();
            textBlock.MinHeight = 1.5;
            scrollControl.DataContext = model;
            stackList.Children.Add(scrollControl);
            stackList.Children.Add(textBlock);
        }

        private void ScrollControl_scrollDelegate(object sender, ListControlModel e)
        {
            ListControlModel model = new ListControlModel();
            hideOrShowOtherButton();
            model = e;
            EditPicControl t = new EditPicControl(model);
            //testgrid.Children.Add(t);
            PicEditView picEditView = new PicEditView(model);
            picEditView.ShowDialog();
        }

        private void CamaraView_Loaded(object sender, RoutedEventArgs e)
        {
           // Thread thread = new Thread(openCamera);
            openCamera();
            //thread.Start();
            
        }

        private void loadCamera()
        {
            worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.DoWork += Worker_DoWork;
            worker.ProgressChanged += Worker_ProgressChanged;
            worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
            worker.RunWorkerAsync();
        }


        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //lbl.Visibility = Visibility.Collapsed;
            if (successed)
                lbl.Visibility = Visibility.Collapsed;
        }

        private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            throw new NotImplementedException();
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            //lbl.Content = "正在打开相机....";
            //Task.Run(() => { lbl.Content = "正在打开相机...."; });
            openCamera();
        }

        //private void callCamera()
        //{
        //    Action act = () => { startCamera(); };
        //    Dispatcher.BeginInvoke(act);
        //}

        //private   async void startCamera()
        //{
        //    //Dispatcher.BeginInvoke((Action)(() =>
        //    //{
        //    //    if (cam_ != null)
        //    //        return;
        //    //    uvcham.Device[] arr = uvcham.Enum();
        //    //    if (arr.Length <= 0)
        //    //        MessageBox.Show("未找到相机");
        //    //    else if (1 == arr.Length)
        //    //        startDevice(arr[0].id);
        //    //}));
        //    lbl.Text = "正在打开相机....ggg";
        //     await Task.Run(() => {
        //         openCamera();
        //    });
            
        //}

        private void openCamera()
        {
            if (cam_ != null)
                return;
            uvcham.Device[] arr = uvcham.Enum();
            if (arr.Length <= 0)
                // MessageBox.Show("未找到相机");
                //lbl.invoke();
                Application.Current.Dispatcher.Invoke(() => lbl.Text = "未找到相机");
            else if (1 == arr.Length)
            {
                successed = true;
                startDevice(arr[0].id);
                //started_=true;
            }
                
        }

        private  void startDevice(string id)
        { 
            cam_ = uvcham.open(id);
            if (cam_ != null)
            {
                cam_.put(uvcham.eCMD.FORMAT,1);
                CommonData.Expo_enabled = true;
                CommonData.balance_enabled = true;
                int width =0, height =0, res=0;
                cam_.get(uvcham.eCMD.RES,out res);
                cam_.get(uvcham.eCMD.WIDTH | ((uvcham.eCMD)res), out width);
                cam_.get(uvcham.eCMD.HEIGHT |((uvcham.eCMD)res), out height);
                //height += 40;
                if ((width > 0)&&(height > 0))
                {                    
                    buf_ = Marshal.AllocHGlobal(uvcham.TDIBWIDTHBYTES(width*32)*height);
                    if (cam_.start(buf_, (nEvent) =>
                    {
                        Dispatcher.BeginInvoke((Action)( () =>
                        {
                        if (cam_ != null)
                        {
                            if ((nEvent & uvcham.eEVENT.IMAGE) != 0)
                            {
                                //lbl.Visibility = Visibility.Collapsed;
                                 //Task.Run(()=> { OnEventImage(); });
                                 OnEventImage(width, height);
                                    //lbl.Text = "UI线程";
                                   // MessageBox.Show("打开了");
                                }
                                    
                                else if((nEvent & uvcham.eEVENT.ERROR)!=0)
                                    OnEventError();
                                else if((nEvent & uvcham.eEVENT.DISCONNECT)!=0)
                                    OnEventDisconnect();


                            }
                        }));
                    }) < 0)
                    {
                        MessageBox.Show("相机启动失败");
                    }
                    else
                    {
                        int nmin, nmax, ndef;
                        cam_.range(uvcham.eCMD.EXPOTIME,out nmin, out nmax, out ndef);
                        CommonData.ExpoSlider_Max = nmax;
                        CommonData.ExpoSlider_Min = nmin;                      
                        cam_.range(uvcham.eCMD.WBRED,out nmin, out nmax,out ndef);
                        CommonData.R_Max = nmax;
                        CommonData.R_Min = nmin;
                        cam_.range(uvcham.eCMD.WBGREEN,out nmin, out nmax, out ndef);
                        CommonData.G_Max = nmax;
                        CommonData.G_Min = nmin;
                        cam_.range(uvcham.eCMD.WBBLUE,out nmin, out nmax, out ndef);
                        CommonData.B_Max = nmax;
                        CommonData.B_Min = nmin;
                        UpdateExpoTime();
                        UpdateAwb();
                        int val = 0;
                        cam_.get(uvcham.eCMD.AEXPO,out val);
                        CommonData.Expo_checked = (1 == val);
                        CommonData.ExpoSlider_enabled = (1!= val);
                        cam_.get(uvcham.eCMD.WBMODE,out val);
                        CommonData.Expo_checked = (1 == val);
                        CommonData.R_enabled = (1 != val);
                        CommonData.G_enabled = (1 != val);
                        CommonData.B_enabled = (1 != val);
                        timer_ = new DispatcherTimer() { Interval = new TimeSpan(0,0,1)};
                        timer_.Tick += (object sender, EventArgs e) =>
                        {
                            if (cam_ != null)
                            {
                                if(CommonData.Expo_checked)
                                UpdateExpoTime();
                                if(CommonData.balance_checked)
                                UpdateAwb();
                            }
                        };
                        timer_.Start();
                    }
                    CommonData.started_ = true;
                }
            }
        }

        private void OnEventImage(int _width, int _height)
        {
            if (bmp_ == null)
            bmp_ = new WriteableBitmap(_width, _height, 0, 0, PixelFormats.Bgr32, null);         
            if (bmp_ != null)
            {
                try
                {
                    bmp_.Lock();
                    try
                    {
                        uvcham.memcpy(bmp_.BackBuffer, buf_, new IntPtr(uvcham.TDIBWIDTHBYTES(bmp_.PixelWidth * 32) * bmp_.PixelHeight));
                        bmp_.AddDirtyRect(new Int32Rect(0, 0, bmp_.PixelWidth, bmp_.PixelHeight));
                    }
                    finally
                    {
                        bmp_.Unlock();
                    }
                    image_.Source = bmp_;
                }
                catch (Exception ex)
                {

                    MessageBox.Show(ex.ToString());
                }
            }


        }
        private static void OnEventError()
        {
            cam_.close();
            cam_ = null;
            Marshal.FreeHGlobal(buf_);
            MessageBox.Show("Generic error");
        }

        private static void OnEventDisconnect()
        {
            cam_.close();
            cam_ = null;
            Marshal.FreeHGlobal(buf_);
            MessageBox.Show("Camera disconnect");
        }

        private static void UpdateExpoTime()
        {
            int val = 0;
            cam_.get(uvcham.eCMD.EXPOTIME,out val);
            CommonData.ExpoSlider_value = val;
        }

        private static void UpdateAwb()
        {
            int val = 0;
            cam_.get(uvcham.eCMD.WBRED,out val);
            CommonData.R_value = val;
            cam_.get(uvcham.eCMD.WBGREEN, out val);
            CommonData.G_value = val;
            cam_.get(uvcham.eCMD.WBBLUE,out val);
            CommonData.B_value = val;
        }

        private void RadioButton_Checked(object sender, RoutedEventArgs e)
        {
            //if ((cam_ != null) && (bmp_ != null))
            //{
            //    using (FileStream fileStream = new FileStream(string.Format("demowpf_{0}.bmp",++count_),FileMode.Create))
            //    { 
            //        BitmapEncoder encoder = new BmpBitmapEncoder();
            //        encoder.Frames.Add(BitmapFrame.Create(bmp_));
            //        encoder.Save(fileStream);
            //    }
            //}
            //PrintView printView = new PrintView();
            //printView.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            //printView.ShowDialog();
        }


        public static void stopCamera()
        {
                cam_?.close();
                cam_ = null;
                Marshal.FreeHGlobal(buf_);           
        }

        private void UserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            //if (started_)
               // stopCamera();
            //else
            //    startCamera();
            //MessageBox.Show("UserControl_DataContextChanged");
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            //callCamera();
        }

        private void UserControl_Initialized(object sender, EventArgs e)
        {
            //startCamera();
        }

        private  async void RadioButton_Click(object sender, RoutedEventArgs e)
        {
            //Dispatcher.BeginInvoke(newMsg("正在连接照相机...."));
            //this.lbl.Content = "正在连接照相机....";
            //Task.Run(() => { showMessage("正在连接照相机...."); });
            //Dispatcher.BeginInvoke(new Action(() => { lbl.Content = "正在连接照相机...."; })) ;
            //Dispatcher.BeginInvoke((Action)(() => { startCamera(); }));

            //startCamera();
            //lbl.Content = "正在连接照相机....";
            //var task = Task.Run(() => { startCamera(); });
            //await task;
            //startCamera();
            //lbl.Content = "正在连接照相机....";

            //Task.Run(() => { startCamera(); });
            //Thread thread = new Thread(() => { startCamera(); });
            //thread.Start();
            //lbl.Dispatcher.BeginInvoke(new Action(() => lbl.Content= "正在连接照相机...."));
            //lbl.Dispatcher.Invoke(() => { startCamera(); });

            //var task startCamera();


        }

        private void photoButton_Click(object sender, RoutedEventArgs e)
        {
            string _pathStr = DateTime.Now.ToString("yyyyMMddHHmmss")+".bmp";
            ListControlModel dt = new ListControlModel();
            if ((cam_ != null) && (bmp_ != null))
            { 
                //using (FileStream fileStream = new FileStream((@"\Image\" +DateTime.Now.ToString("yyyyMMddHHmmss")), FileMode.Create))
                using (FileStream fileStream = new FileStream(_pathStr, FileMode.Create))
                { 
                    BitmapEncoder encoder = new BmpBitmapEncoder ();
                    encoder.Frames.Add(BitmapFrame.Create(bmp_));
                    encoder.Save(fileStream);
                    //camModel.VM_Model.Add(new Model() { Path = System.AppDomain.CurrentDomain.BaseDirectory+ _pathStr });
                    //CameraViewModel.camModel.VM_Model.Add(new Model() { Path = System.AppDomain.CurrentDomain.BaseDirectory + _pathStr,Name=_pathStr.Substring(0,_pathStr.LastIndexOf(".")) });
                }
                ListControlModel model = new ListControlModel { ImgPath = System.AppDomain.CurrentDomain.BaseDirectory + _pathStr, Name = _pathStr };
                ScrollControl scrollControl = new ScrollControl();
                TextBlock textBlock = new TextBlock();
                textBlock.MinHeight = 1.5;
                scrollControl.DataContext = model;
                stackList.Children.Add(scrollControl);
                stackList.Children.Add(textBlock);
                /****************************************************************/
                if (dt != null)
                {
                    dt.ImgPath = System.AppDomain.CurrentDomain.BaseDirectory + _pathStr;
                    dt.ImageName = _pathStr;
                    EditPicControl t = new EditPicControl(dt);
                    testgrid.Children.Add(t);
                }
                
            }
        }

        private void openCam_Click(object sender, RoutedEventArgs e)
        {
            //if (!started_)
            //    loadCamera();
        }

        private void MaxBtn_Click(object sender, RoutedEventArgs e)
        {          

            if (!_maxed)
            {
                if (_fullScreenWindow == null)
                {
                    _fullScreenWindow = new Window();


                    WindowOperator.RemoveFromParent(this.testgrid, out _originalParent, out index);




                    _fullScreenWindow.Content = this.testgrid;
                    _fullScreenWindow.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#6495ED")); 
                    _fullScreenWindow.WindowStyle = WindowStyle.None;
                    _fullScreenWindow.WindowState = WindowState.Maximized;
                    _fullScreenWindow.ResizeMode = ResizeMode.NoResize;
                    _fullScreenWindow.Show();
                    _maxed = true;
                }
            }
            else
            {
                var faSub = VisualTreeHelper.GetParent(this.testgrid);
                var loc = LogicalTreeHelper.GetParent(this.testgrid);
                RemoveChild(faSub,this.testgrid);
                RemoveChild(loc, this.testgrid);
                WindowOperator.AddToParent(this.testgrid, _originalParent, index);
                _fullScreenWindow.Close();
                _fullScreenWindow = null;
                _maxed=false;
            }
            
        }

        //private void find(DependencyObject parent)
        //{
        //    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
        //    {
        //        var child = VisualTreeHelper.GetChild(parent, i);
        //        string name = child.GetValue(Control.NameProperty) as string;
        //        if ((name != "imagePanel") && (name != "operPanel"))
        //            child.SetValue(Control.VisibilityProperty,Visibility.Hidden);
        //    }
        //}

        private void RemoveChild( DependencyObject parent,UIElement child)
        { 
            var panel = parent as Panel;
            if (panel != null) 
            {
                panel.Children.Remove(child);
                return;
            }
             var decorator = parent as Decorator;
            if (decorator != null)
            {
                if (decorator.Child == child)
                {
                    decorator.Child = null;
                }
                return;
            }
            var contentPresenter = parent as ContentPresenter;
            if (contentPresenter != null) 
            {
                if (contentPresenter.Content == child)
                {
                    contentPresenter.Content = null;
                }
                return;
            }
            var contentControl = parent as ContentControl;
            if (contentControl != null)
            {
                if (contentControl.Content == child)
                {
                    contentControl.Content = null;
                }

                return;
            }
        }

        private void AddParent(DependencyObject parent, UIElement child)
        {
            if (parent is ContentControl contentControl)
                contentControl.Content = child;
        }

        public void RemoveChild2(Grid parent, UIElement child)
        {
            var grid = parent as Grid;
            if (grid != null)
            {
                if (grid.Children.Contains(child))
                {
                    grid.Children.Remove(child);
                }
            }
        }

        private void setBtn_Click(object sender, RoutedEventArgs e)
        {
            if (settingWindow == null)
            {
                settingWindow = new CameraSettingWindow();

                settingWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                settingWindow.ShowDialog();              
            }

            if (settingWindow.DialogResult != true)
                settingWindow = null;
        }

       public void hideOrShowOtherButton()
        {
            List<Button> btnList = WindowOperator.FindVisualChild<Button>(this.operPanel);
            foreach (var item in btnList)
            {
                if(item != null)
                    if(item.Name != "MaxBtn")
                        if(item.Visibility != Visibility.Visible)
                            item.Visibility = Visibility.Visible;
                        else
                            item.Visibility = Visibility.Collapsed;
            }
        }


        private void InputBtn_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.DialogResult res = System.Windows.Forms.MessageBox.Show("导入的图像可能不属于该病人，需要继续导入吗？","确认", (System.Windows.Forms.MessageBoxButtons)MessageBoxButton.YesNo);
            if (res == System.Windows.Forms.DialogResult.Yes)
            {
                OpenFileWindow openFileWindow = new OpenFileWindow();
                openFileWindow.uploadDelegate += OpenFileWindow_uploadDelegate;
                openFileWindow.ShowDialog();
                
            }
        }
        
        private void OpenFileWindow_uploadDelegate(object sender, ListControlModel e)
        {
            ListControlModel model = new ListControlModel { ImgPath = e.ImgPath, Name=e.Name};
            ScrollControl scrollControl = new ScrollControl();
            TextBlock textBlock = new TextBlock();
            textBlock.MinHeight = 1.5;
            scrollControl.DataContext = model;
            stackList.Children.Add(scrollControl);
            stackList.Children.Add(textBlock);
        }

        private void Image_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
           // var tem = sender as Image;
           // var t2 = tem.DataContext as CameraModel.Model;
           // ListControlModel picInputModel = new ListControlModel();
           // hideOrShowOtherButton();         
           // picInputModel.Path = t2.Path;
           // picInputModel.Name = t2.Name;
           //EditPicControl t = new EditPicControl(picInputModel);
           // testgrid.Children.Add(t);
            
        }

        private void picList_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var t = e.Source.ToString();
           
        }

        private void checkName_Checked(object sender, RoutedEventArgs e)
        {
            // if(this.picList.)
            
        }

        private void checkName_Unchecked(object sender, RoutedEventArgs e)
        {

        }

        private void checkName_Click(object sender, RoutedEventArgs e)
        {
            var d = ((CheckBox)sender).DataContext;
        }

        private void TextBox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var t =((TextBox)sender) as TextBox;
            if (t.IsEnabled == false)
                t.IsEnabled = true;
        }
    }
}
